package com.kakarote.examine.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONObject;
import com.kakarote.core.entity.UserInfo;
import com.kakarote.core.feign.admin.entity.SimpleUser;
import com.kakarote.core.feign.admin.service.AdminService;
import com.kakarote.core.feign.examine.entity.ExamineDataSaveBO;
import com.kakarote.core.feign.examine.entity.ExamineFlowVO;
import com.kakarote.core.servlet.ApplicationContextHolder;
import com.kakarote.core.utils.UserUtil;
import com.kakarote.examine.constant.ExamineStatusEnum;
import com.kakarote.examine.constant.ExamineTypeEnum;
import com.kakarote.examine.entity.PO.*;
import com.kakarote.examine.service.impl.ExamineConditionServiceImpl;
import com.kakarote.examine.service.impl.ExamineFlowCopyServiceImpl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 审批类型service
 */
public interface ExamineTypeService {


    /**
     * 保存额外的审批流程data对象
     *
     * @param dataSaveBO data
     * @param flowId     审批流程ID
     * @param batchId    批次ID
     */
    void saveExamineFlowData(ExamineDataSaveBO dataSaveBO, Long flowId, String batchId);


    /**
     * 通过batchId查询所有flow关联对象
     *
     * @param map     缓存对象
     * @param batchId batchId
     */
    void queryFlowListByBatchId(Map<String, Object> map, String batchId);


    /**
     * 查询详情页需要的审批详情
     *
     * @param examineFlow 当前审批流程
     * @param map         缓存的map
     * @param allUserList 所有用户列表
     * @param ownerUserId 当前审批的用户ID
     * @return data
     */
    ExamineFlowVO createFlowInfo(ExamineFlow examineFlow, Map<String, Object> map, List<UserInfo> allUserList, Long ownerUserId);

    /**
     * 用户信息转simpleUser
     *
     * @param userInfo 用户信息
     * @return simpleUser
     */
    default SimpleUser toSimPleUser(UserInfo userInfo) {
        SimpleUser simpleUser = new SimpleUser();
        simpleUser.setUserId(userInfo.getUserId());
        simpleUser.setRealname(userInfo.getRealname());
        simpleUser.setImg(userInfo.getImg());
        return simpleUser;
    }


    /**
     * 查询当前状态为正常的用户
     *
     * @param userIds 用户ID列表
     * @return 状态为正常的用户列表
     */
    default List<Long> handleUserIdList(List<Long> userIds) {
        List<Long> userList = new ArrayList<>();
        if (CollUtil.isNotEmpty(userIds)) {
            AdminService adminService = ApplicationContextHolder.getBean(AdminService.class);
            userList = adminService.queryNormalUserByIds(userIds).getData();
            userList.retainAll(userIds);
        }
        return userList;
    }

    /**
     * 保存选人审批的用户
     *
     * @param userList 用户列表
     * @param flowId   审批流程ID
     * @param recordId 审批记录ID
     * @param type     审批类型
     * @return data
     */
    default List<ExamineFlowFinalOptional> castFlowOptionalUser(List<Long> userList, Long flowId, Long recordId, Integer type) {
        if (userList == null || userList.isEmpty()) {
            return new ArrayList<>();
        }
        List<ExamineFlowFinalOptional> flowFinalOptionals = new ArrayList<>(userList.size());
        Long createUserId = UserUtil.getUserId();
        int i = 0;
        Date date = new Date();
        for (Long userId : userList) {
            ExamineFlowFinalOptional examineFlowFinalOptional = new ExamineFlowFinalOptional();
            examineFlowFinalOptional.setCreateTime(date);
            examineFlowFinalOptional.setCreateUserId(createUserId);
            examineFlowFinalOptional.setFlowId(flowId);
            examineFlowFinalOptional.setRecordId(recordId);
            examineFlowFinalOptional.setSort(i++);
            examineFlowFinalOptional.setType(type);
            examineFlowFinalOptional.setUserId(userId);
            flowFinalOptionals.add(examineFlowFinalOptional);
        }
        return flowFinalOptionals;
    }

    /**
     * 处理审批日志记录无有效审核人的问题
     *
     * @param recordId 审核记录ID
     * @param flowId   节点ID
     * @param init     是否初始化
     * @param data     特殊节点处理所需数据
     * @return 审批状态
     */
    default Integer handleRecordLogByAdvancedConfig(Long recordId, Long flowId, Boolean init, Object data) {

        if (this instanceof ExamineConditionServiceImpl || this instanceof ExamineFlowCopyServiceImpl) {
            return null;
        }

        ExamineFlowFinal flowFinal = ApplicationContextHolder.getBean(IExamineFlowFinalService.class).lambdaQuery().eq(
                ExamineFlowFinal::getFlowId, flowId).eq(ExamineFlowFinal::getRecordId, recordId).one();

        List<ExamineRecordLog> recordLogList = ApplicationContextHolder.getBean(IExamineRecordLogService.class).lambdaQuery().eq(ExamineRecordLog::getFlowId, flowId).eq(ExamineRecordLog::getRecordId, recordId).list();

        recordLogList = recordLogList.stream().filter(recordLog -> !recordLog.getExamineStatus().equals(ExamineStatusEnum.CREATE.getStatus())).collect(Collectors.toList());

        if (flowFinal.getExamineType().equals(ExamineTypeEnum.OPTIONAL.getType())) {
            if (recordLogList.size() == 0) {
                return ExamineStatusEnum.UNDERWAY.getStatus();
            }
        }
        if (flowFinal.getExamineType().equals(ExamineTypeEnum.COPY.getType())) {
            return ExamineStatusEnum.UNDERWAY.getStatus();
        }
        return ApplicationContextHolder.getBean(IExamineAdvancedConfigService.class).handleRecordLogByAdvancedConfig(recordLogList, flowFinal, init, data);
    }

    /**
     * 处理当前节点
     *
     * @param examineFlow 当前处理节点
     * @param recordId    审核记录ID
     * @param data        特殊处理所需数据(具体看实现类)
     * @param examine     审核对象
     * @param init        是否初始化
     * @return data
     */
    default JSONObject disposeFlow(ExamineFlow examineFlow, Long recordId, Object data, Examine examine, boolean init) {
        return new JSONObject().putOpt("status", ExamineStatusEnum.UNDERWAY.getStatus());
    }

    /**
     * 获取执行的审批流程
     *
     * @param examineFlow
     * @param examineRecord
     * @param dataMap
     * @return
     */
    default ExamineFlow getAvailableFlow(ExamineFlow examineFlow, ExamineRecord examineRecord, Map<String, Object> dataMap) {
        return examineFlow;
    }
}
